package com.forcetools.utils;

import com.sforce.soap.metadata.MetadataConnection;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
import org.apache.log4j.Logger;
import java.util.Map;
import java.util.HashMap;

public class ConnectionUtils {
	private static Map<String,PartnerConnection> partnerConnMap;
	private static Map<String,MetadataConnection> metaConnMap;
	private static Logger logger;
	static{
		logger = Logger.getLogger(ConnectionUtils.class);
		partnerConnMap = new HashMap<String,PartnerConnection>();
		metaConnMap = new HashMap<String,MetadataConnection>();
	}
	
	public static MetadataConnection getMetadataConnection(String envPrefix) throws Exception {
		if(!metaConnMap.containsKey(envPrefix)){
			try{
				metaConnMap.put(envPrefix, getMetaConnection(	PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.username"),
																PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.password"),
																PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.loginUrl")));
			}catch(Exception ex){
				logger.error("Could not load connection properties for "+envPrefix);
				throw ex;
			}
		}
		return metaConnMap.get(envPrefix); 
	}
	public static PartnerConnection getPartnerConnection(String envPrefix) throws Exception {
		if(!partnerConnMap.containsKey(envPrefix)){
			try{
				partnerConnMap.put(envPrefix, getPartnerConnection(	PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.username"),
																	PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.password"),
																	PropertyConfigUtils.getProperty("sfdc_connection",envPrefix, "salesforce.loginUrl")));
			}catch(Exception ex){
				logger.error("Could not load connection properties for "+envPrefix);
				throw ex;
			}
		}
		return partnerConnMap.get(envPrefix); 
	}
	private static PartnerConnection getPartnerConnection(String username,String password,String loginUrl) throws Exception  {
		PartnerConnection connection=null;
		try { 
		   logger.debug("Establishing new connection");
		   // login to the Force.com Platform
		   ConnectorConfig config = new ConnectorConfig();
		   config.setUsername(username);
		   config.setPassword(password);
		   config.setAuthEndpoint(loginUrl);
		   connection = com.sforce.soap.partner.Connector.newConnection(config);
		   logger.debug("Session Id :"+ connection.getConfig().getSessionId() );
		   logger.debug("Service Endpoint:"+connection.getConfig().getServiceEndpoint() );
		} catch ( ConnectionException ce) {
			logger.debug("ConnectionException " +ce.getMessage());
			
			logger.debug( ce.getMessage() + " s " + ce.getClass() );
		}
	   return connection;
		
	}

	private static MetadataConnection getMetaConnection(String username,String password,String loginUrl) throws Exception  {
		PartnerConnection connection=getPartnerConnection(username,password,loginUrl);
		MetadataConnection metaConnection;
		
		try { 
		   ConnectorConfig metaConfig = new ConnectorConfig();
		   metaConfig.setSessionId(connection.getConfig().getSessionId());
		   metaConfig.setServiceEndpoint(getMetaDataServiceEndpoint(connection.getConfig().getServiceEndpoint()));
		   metaConnection = com.sforce.soap.metadata.Connector.newConnection(metaConfig);
		   logger.debug( "Metadata Session Id:"+ metaConnection.getConfig().getSessionId() );
		   logger.debug( "Metadata Endpoint:"+metaConnection.getConfig().getServiceEndpoint() );
		}catch(Exception ex){
			logger.error("Error establishing Metadata connection");
			throw ex;
		}
		return metaConnection;
	}

	private static String getMetaDataServiceEndpoint(String apiEndpoint){
		String metaAPIEndpoint="";
		String[] tokens = apiEndpoint.split("/");
		metaAPIEndpoint+=tokens[0];
		metaAPIEndpoint+="//";
		
		for(Integer idx=2;idx<tokens.length-1;idx++){
			if(tokens[idx].equals("u")){
				metaAPIEndpoint+="m";
			}else{
				metaAPIEndpoint+=tokens[idx];
			}
			metaAPIEndpoint +="/";
		}
		return metaAPIEndpoint+tokens[tokens.length-1];
	}
}
